﻿using System;
using UnityEngine;

namespace RootMotion.FinalIK
{
	// Token: 0x02000163 RID: 355
	[Serializable]
	public class IKEffector
	{
		// Token: 0x06000602 RID: 1538 RVA: 0x0001CB84 File Offset: 0x0001AF84
		public IKEffector()
		{
		}

		// Token: 0x06000603 RID: 1539 RVA: 0x0001CC2C File Offset: 0x0001B02C
		public IKEffector(Transform bone, Transform[] childBones)
		{
			this.bone = bone;
			this.childBones = childBones;
		}

		// Token: 0x06000604 RID: 1540 RVA: 0x0001CCE1 File Offset: 0x0001B0E1
		public IKSolver.Node GetNode(IKSolverFullBody solver)
		{
			return solver.chain[this.chainIndex].nodes[this.nodeIndex];
		}

		// Token: 0x1700004F RID: 79
		// (get) Token: 0x06000605 RID: 1541 RVA: 0x0001CCFC File Offset: 0x0001B0FC
		// (set) Token: 0x06000606 RID: 1542 RVA: 0x0001CD04 File Offset: 0x0001B104
		public bool isEndEffector { get; private set; }

		// Token: 0x06000607 RID: 1543 RVA: 0x0001CD10 File Offset: 0x0001B110
		public void PinToBone(float positionWeight, float rotationWeight)
		{
			this.position = this.bone.position;
			this.positionWeight = Mathf.Clamp(positionWeight, 0f, 1f);
			this.rotation = this.bone.rotation;
			this.rotationWeight = Mathf.Clamp(rotationWeight, 0f, 1f);
		}

		// Token: 0x06000608 RID: 1544 RVA: 0x0001CD6C File Offset: 0x0001B16C
		public bool IsValid(IKSolver solver, ref string message)
		{
			if (this.bone == null)
			{
				message = "IK Effector bone is null.";
				return false;
			}
			if (solver.GetPoint(this.bone) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.bone.name + "' that does not excist in the Node Chain.";
				return false;
			}
			foreach (Transform x in this.childBones)
			{
				if (x == null)
				{
					message = "IK Effector contains a null reference.";
					return false;
				}
			}
			foreach (Transform transform in this.childBones)
			{
				if (solver.GetPoint(transform) == null)
				{
					message = "IK Effector is referencing to a bone '" + transform.name + "' that does not excist in the Node Chain.";
					return false;
				}
			}
			if (this.planeBone1 != null && solver.GetPoint(this.planeBone1) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone1.name + "' that does not excist in the Node Chain.";
				return false;
			}
			if (this.planeBone2 != null && solver.GetPoint(this.planeBone2) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone2.name + "' that does not excist in the Node Chain.";
				return false;
			}
			if (this.planeBone3 != null && solver.GetPoint(this.planeBone3) == null)
			{
				message = "IK Effector is referencing to a bone '" + this.planeBone3.name + "' that does not excist in the Node Chain.";
				return false;
			}
			return true;
		}

		// Token: 0x06000609 RID: 1545 RVA: 0x0001CF04 File Offset: 0x0001B304
		public void Initiate(IKSolverFullBody solver)
		{
			this.position = this.bone.position;
			this.rotation = this.bone.rotation;
			this.animatedPlaneRotation = Quaternion.identity;
			solver.GetChainAndNodeIndexes(this.bone, out this.chainIndex, out this.nodeIndex);
			this.childChainIndexes = new int[this.childBones.Length];
			this.childNodeIndexes = new int[this.childBones.Length];
			for (int i = 0; i < this.childBones.Length; i++)
			{
				solver.GetChainAndNodeIndexes(this.childBones[i], out this.childChainIndexes[i], out this.childNodeIndexes[i]);
			}
			this.localPositions = new Vector3[this.childBones.Length];
			this.usePlaneNodes = false;
			if (this.planeBone1 != null)
			{
				solver.GetChainAndNodeIndexes(this.planeBone1, out this.plane1ChainIndex, out this.plane1NodeIndex);
				if (this.planeBone2 != null)
				{
					solver.GetChainAndNodeIndexes(this.planeBone2, out this.plane2ChainIndex, out this.plane2NodeIndex);
					if (this.planeBone3 != null)
					{
						solver.GetChainAndNodeIndexes(this.planeBone3, out this.plane3ChainIndex, out this.plane3NodeIndex);
						this.usePlaneNodes = true;
					}
				}
				this.isEndEffector = true;
			}
			else
			{
				this.isEndEffector = false;
			}
		}

		// Token: 0x0600060A RID: 1546 RVA: 0x0001D06C File Offset: 0x0001B46C
		public void ResetOffset(IKSolverFullBody solver)
		{
			solver.GetNode(this.chainIndex, this.nodeIndex).offset = Vector3.zero;
			for (int i = 0; i < this.childChainIndexes.Length; i++)
			{
				solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).offset = Vector3.zero;
			}
		}

		// Token: 0x0600060B RID: 1547 RVA: 0x0001D0CE File Offset: 0x0001B4CE
		public void SetToTarget()
		{
			if (this.target == null)
			{
				return;
			}
			this.position = this.target.position;
			this.rotation = this.target.rotation;
		}

		// Token: 0x0600060C RID: 1548 RVA: 0x0001D104 File Offset: 0x0001B504
		public void OnPreSolve(IKSolverFullBody solver)
		{
			this.positionWeight = Mathf.Clamp(this.positionWeight, 0f, 1f);
			this.rotationWeight = Mathf.Clamp(this.rotationWeight, 0f, 1f);
			this.maintainRelativePositionWeight = Mathf.Clamp(this.maintainRelativePositionWeight, 0f, 1f);
			this.posW = this.positionWeight * solver.IKPositionWeight;
			this.rotW = this.rotationWeight * solver.IKPositionWeight;
			solver.GetNode(this.chainIndex, this.nodeIndex).effectorPositionWeight = this.posW;
			solver.GetNode(this.chainIndex, this.nodeIndex).effectorRotationWeight = this.rotW;
			solver.GetNode(this.chainIndex, this.nodeIndex).solverRotation = this.rotation;
			if (float.IsInfinity(this.positionOffset.x) || float.IsInfinity(this.positionOffset.y) || float.IsInfinity(this.positionOffset.z))
			{
				Debug.LogError("Invalid IKEffector.positionOffset (contains Infinity)! Please make sure not to set IKEffector.positionOffset to infinite values.", this.bone);
			}
			if (float.IsNaN(this.positionOffset.x) || float.IsNaN(this.positionOffset.y) || float.IsNaN(this.positionOffset.z))
			{
				Debug.LogError("Invalid IKEffector.positionOffset (contains NaN)! Please make sure not to set IKEffector.positionOffset to NaN values.", this.bone);
			}
			if (this.positionOffset.sqrMagnitude > 1E+10f)
			{
				Debug.LogError("Additive effector positionOffset detected in Full Body IK (extremely large value). Make sure you are not circularily adding to effector positionOffset each frame.", this.bone);
			}
			if (float.IsInfinity(this.position.x) || float.IsInfinity(this.position.y) || float.IsInfinity(this.position.z))
			{
				Debug.LogError("Invalid IKEffector.position (contains Infinity)!");
			}
			solver.GetNode(this.chainIndex, this.nodeIndex).offset += this.positionOffset * solver.IKPositionWeight;
			if (this.effectChildNodes && solver.iterations > 0)
			{
				for (int i = 0; i < this.childBones.Length; i++)
				{
					this.localPositions[i] = this.childBones[i].transform.position - this.bone.transform.position;
					solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).offset += this.positionOffset * solver.IKPositionWeight;
				}
			}
			if (this.usePlaneNodes && this.maintainRelativePositionWeight > 0f)
			{
				this.animatedPlaneRotation = Quaternion.LookRotation(this.planeBone2.position - this.planeBone1.position, this.planeBone3.position - this.planeBone1.position);
			}
			this.firstUpdate = true;
		}

		// Token: 0x0600060D RID: 1549 RVA: 0x0001D420 File Offset: 0x0001B820
		public void OnPostWrite()
		{
			this.positionOffset = Vector3.zero;
		}

		// Token: 0x0600060E RID: 1550 RVA: 0x0001D430 File Offset: 0x0001B830
		private Quaternion GetPlaneRotation(IKSolverFullBody solver)
		{
			Vector3 solverPosition = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition;
			Vector3 solverPosition2 = solver.GetNode(this.plane2ChainIndex, this.plane2NodeIndex).solverPosition;
			Vector3 solverPosition3 = solver.GetNode(this.plane3ChainIndex, this.plane3NodeIndex).solverPosition;
			Vector3 vector = solverPosition2 - solverPosition;
			Vector3 upwards = solverPosition3 - solverPosition;
			if (vector == Vector3.zero)
			{
				Warning.Log("Make sure you are not placing 2 or more FBBIK effectors of the same chain to exactly the same position.", this.bone, false);
				return Quaternion.identity;
			}
			return Quaternion.LookRotation(vector, upwards);
		}

		// Token: 0x0600060F RID: 1551 RVA: 0x0001D4C8 File Offset: 0x0001B8C8
		public void Update(IKSolverFullBody solver)
		{
			if (this.firstUpdate)
			{
				this.animatedPosition = this.bone.position + solver.GetNode(this.chainIndex, this.nodeIndex).offset;
				this.firstUpdate = false;
			}
			solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition = Vector3.Lerp(this.GetPosition(solver, out this.planeRotationOffset), this.position, this.posW);
			if (!this.effectChildNodes)
			{
				return;
			}
			for (int i = 0; i < this.childBones.Length; i++)
			{
				solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition = Vector3.Lerp(solver.GetNode(this.childChainIndexes[i], this.childNodeIndexes[i]).solverPosition, solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition + this.localPositions[i], this.posW);
			}
		}

		// Token: 0x06000610 RID: 1552 RVA: 0x0001D5DC File Offset: 0x0001B9DC
		private Vector3 GetPosition(IKSolverFullBody solver, out Quaternion planeRotationOffset)
		{
			planeRotationOffset = Quaternion.identity;
			if (!this.isEndEffector)
			{
				return solver.GetNode(this.chainIndex, this.nodeIndex).solverPosition;
			}
			if (this.maintainRelativePositionWeight <= 0f)
			{
				return this.animatedPosition;
			}
			Vector3 a = this.bone.position;
			Vector3 point = a - this.planeBone1.position;
			planeRotationOffset = this.GetPlaneRotation(solver) * Quaternion.Inverse(this.animatedPlaneRotation);
			a = solver.GetNode(this.plane1ChainIndex, this.plane1NodeIndex).solverPosition + planeRotationOffset * point;
			planeRotationOffset = Quaternion.Lerp(Quaternion.identity, planeRotationOffset, this.maintainRelativePositionWeight);
			return Vector3.Lerp(this.animatedPosition, a + solver.GetNode(this.chainIndex, this.nodeIndex).offset, this.maintainRelativePositionWeight);
		}

		// Token: 0x04000332 RID: 818
		public Transform bone;

		// Token: 0x04000333 RID: 819
		public Transform target;

		// Token: 0x04000334 RID: 820
		[Range(0f, 1f)]
		public float positionWeight;

		// Token: 0x04000335 RID: 821
		[Range(0f, 1f)]
		public float rotationWeight;

		// Token: 0x04000336 RID: 822
		public Vector3 position = Vector3.zero;

		// Token: 0x04000337 RID: 823
		public Quaternion rotation = Quaternion.identity;

		// Token: 0x04000338 RID: 824
		public Vector3 positionOffset;

		// Token: 0x0400033A RID: 826
		public bool effectChildNodes = true;

		// Token: 0x0400033B RID: 827
		[Range(0f, 1f)]
		public float maintainRelativePositionWeight;

		// Token: 0x0400033C RID: 828
		public Transform[] childBones = new Transform[0];

		// Token: 0x0400033D RID: 829
		public Transform planeBone1;

		// Token: 0x0400033E RID: 830
		public Transform planeBone2;

		// Token: 0x0400033F RID: 831
		public Transform planeBone3;

		// Token: 0x04000340 RID: 832
		public Quaternion planeRotationOffset = Quaternion.identity;

		// Token: 0x04000341 RID: 833
		private float posW;

		// Token: 0x04000342 RID: 834
		private float rotW;

		// Token: 0x04000343 RID: 835
		private Vector3[] localPositions = new Vector3[0];

		// Token: 0x04000344 RID: 836
		private bool usePlaneNodes;

		// Token: 0x04000345 RID: 837
		private Quaternion animatedPlaneRotation = Quaternion.identity;

		// Token: 0x04000346 RID: 838
		private Vector3 animatedPosition;

		// Token: 0x04000347 RID: 839
		private bool firstUpdate;

		// Token: 0x04000348 RID: 840
		private int chainIndex = -1;

		// Token: 0x04000349 RID: 841
		private int nodeIndex = -1;

		// Token: 0x0400034A RID: 842
		private int plane1ChainIndex;

		// Token: 0x0400034B RID: 843
		private int plane1NodeIndex = -1;

		// Token: 0x0400034C RID: 844
		private int plane2ChainIndex = -1;

		// Token: 0x0400034D RID: 845
		private int plane2NodeIndex = -1;

		// Token: 0x0400034E RID: 846
		private int plane3ChainIndex = -1;

		// Token: 0x0400034F RID: 847
		private int plane3NodeIndex = -1;

		// Token: 0x04000350 RID: 848
		private int[] childChainIndexes = new int[0];

		// Token: 0x04000351 RID: 849
		private int[] childNodeIndexes = new int[0];
	}
}
